﻿#include "unrealircd.h"
#include "h.h"

CMD_FUNC(cmd_addFriend);
CMD_FUNC(cmd_agreeFriend);
CMD_FUNC(cmd_showAllFriends);

ModuleHeader MOD_HEADER
= {
	"third/friends",
	"1.1",
	"This module will add, delete, change, check and other operations to the database",
	"waitch",
	"unrealircd-5",
};

MOD_INIT()
{
	
    CommandAdd(modinfo->handle, "ADDFRIEND", cmd_addFriend, 1, CMD_USER);
    CommandAdd(modinfo->handle, "AGREEFRIEND", cmd_agreeFriend, 2, CMD_USER);
    CommandAdd(modinfo->handle, "SHOWALLFRIENDS", cmd_showAllFriends, 0, CMD_USER);
	return MOD_SUCCESS;
}

MOD_LOAD()
{
	return MOD_SUCCESS;
}

MOD_UNLOAD()
{
	return MOD_SUCCESS;
}

/**
 * @brief 申请添加好友
 * parv[1]: 好友id
 * 
 */
CMD_FUNC(cmd_addFriend){
    if (parc != 2 || BadPtr(parv[1]) || !is_digist_string(parv[1],strlen(parv[1]))) {
		sendnumeric(client, PARAMERROR, "ADDFRIEND","parv[1]");
		return;
	}
    if(atoi(parv[1])==client->user_id){
        sendnumeric(client, PARAMERROR, "ADDFRIEND","can't add self");
		return;
    }
    int userLength = 0;
    D_User * user = queryImUserById(atoi(parv[1]),&userLength);
    if(!user){
        sendnumeric(client, ADDFRIENDFAILE,"user is not exited");
        return;
    }
    int relationLength = 0;
    D_im_user_relation * relations = queryImUserRelationByUserIdAndFriendId(client->user_id,atoi(parv[1]),&relationLength);
    if(relationLength == 1){
        db_D_imUserRelationFree(relations,relationLength);
        db_D_UserFree(user,userLength);
        sendnumeric(client, ADDFRIENDFAILE,"you are already friends");
        return;
    }
    D_im_relation_applicant * app = db_createRelationApplicant();
#define XX(name,value,type) \
    name = (type*)safe_alloc(sizeof(type)); \
    *(name) = value;

    XX(app->applicant_id, client->user_id,int);
    XX(app->applicant_status, NOSELECT,int);
    XX(app->applicant_type, ADDFRIEND,int);
    XX(app->respondent_id, *(user->id),int);

#undef XX
    app->applicant_time = (D_TimeStamp*)safe_alloc(sizeof(D_TimeStamp));
    D_getCurrectTime(app->applicant_time);
    int datalen = 0;
    D_im_relation_applicant *insertApps = InsertImRelationApplicant(app, &datalen);
    if(datalen == -1){ 
        sendnumeric(client, ADDFRIENDFAILE,"database faile");
    }
    else{
        Client* friendClient = hash_find_client(user->user_name,NULL);
        if(friendClient){ //    申请添加的好友在线，则向好友发送收到申请的消息
            cJSON * result_json = cJSON_CreateObject();
            char appTimep[20];
            db_timestamp_to_string(insertApps->applicant_time,appTimep);
            cJSON_AddStringToObject(result_json, "ApplicantTime",appTimep);
            cJSON_AddNumberToObject(result_json,"ApplicantId",*(insertApps->relation_applicant_id));
            cJSON_AddNumberToObject(result_json,"ApplicantUserId",client->user_id);
            cJSON_AddStringToObject(result_json,"ApplicantUserName", client->user->username);
            cJSON_AddStringToObject(result_json,"ApplicantUserNick", client->info);
            sendnumeric(friendClient, RECEFRIENDAPPLICATION,cJSON_PrintUnformatted(result_json));
            cJSON_Delete(result_json);
        }
        sendnumeric(client, ADDFRIENDSUCCESS);
    }




    db_D_imRelationApplicantFree(app,1);
    db_D_imRelationApplicantFree(insertApps,datalen); 
    db_D_UserFree(user,userLength);
}

/**
 * @brief 同意好友的添加
 * parv[1]: 好友的申请id
 * parv[2]: 好友的nick_name
 */
CMD_FUNC(cmd_agreeFriend){
    if(parc<2){
        sendnumeric(client, PARAMERROR, "AGREEFRIEND","parv[1]");
		return;
    }
    int id = -1;
    char* nick_name = NULL;
    if(parc>=2 && !BadPtr(parv[1]) && is_digist_string(parv[1],strlen(parv[1]))){
        id = atoi(parv[1]);
    }
    if(id == -1){
        sendnumeric(client, PARAMERROR, "AGREEFRIEND","parv[1]");
		return;
    }
    if(parc >= 3 && !BadPtr(parv[2])){
        safe_strdup(nick_name,parv[2]);
    }
    int relationApplicantLength = 0;
    D_im_relation_applicant * relationApplicants = queryImRelationApplicantByRelationApplicantId(id,&relationApplicantLength);
    if(relationApplicantLength == 0 || *(relationApplicants->respondent_id) != client->user_id){
        sendnumeric(client, AGREEFRIENDFAILE,"applicant id is not correct");
        return;
    }
    if(relationApplicants && *(relationApplicants->applicant_status)!=1){
        db_D_imRelationApplicantFree(relationApplicants,relationApplicantLength);
        sendnumeric(client, AGREEFRIENDFAILE,"applicant is already handle");
        return;
    }
    int userRelation1Length = 0;
    D_im_user_relation * userRelation1 = queryImUserRelationByUserIdAndFriendId(client->user_id,*(relationApplicants->applicant_id),&userRelation1Length);
    int userRelation2Length = 0;
    D_im_user_relation * userRelation2 = queryImUserRelationByUserIdAndFriendId(*(relationApplicants->applicant_id),client->user_id,&userRelation2Length);
    if(userRelation1Length==1&&userRelation2Length==1){
        sendnumeric(client, AGREEFRIENDFAILE,"unable to add friends repeatedly");
    }else{
        D_im_user_relation * userRelation = db_createUserRelation();
        userRelation->user_id = safe_alloc(sizeof(int));
        userRelation->friend_id = safe_alloc(sizeof(int));
        
        int flag = 0;
        if(userRelation2Length == 0){
            *(userRelation->friend_id) = client->user_id;
            *(userRelation->user_id) = *(relationApplicants->applicant_id);
            int insertUserRelationLength = 0;
            D_im_user_relation * insertUserRelation = InsertImUserRelation(userRelation,&insertUserRelationLength);
            if(insertUserRelationLength!=1){
                flag = 1;
            }
            db_D_imUserRelationFree(insertUserRelation,insertUserRelationLength);
        }
        if(userRelation1Length == 0){
            *(userRelation->user_id) = client->user_id;
            *(userRelation->friend_id) = *(relationApplicants->applicant_id);
            if(nick_name){
                safe_strdup(userRelation->nick_name,nick_name);
            }
            int insertUserRelationLength = 0;
            D_im_user_relation * insertUserRelation = InsertImUserRelation(userRelation,&insertUserRelationLength);
            if(insertUserRelationLength!=1){
                flag = 1;
            }
            db_D_imUserRelationFree(insertUserRelation,insertUserRelationLength);
        }
        if(flag==1){
            sendnumeric(client, AGREEFRIENDFAILE,"database faile");
        }
        else{
            int updateLen = 0;
            *(relationApplicants->applicant_status) = AGREE;
            D_im_relation_applicant *updata = UpdataImRelationApplicant(relationApplicants,&updateLen);
            db_D_imRelationApplicantFree(updata,updateLen);
            sendnumeric(client, AGREEFRIENDSUCCESS);
        }
        db_D_imUserRelationFree(userRelation,1);
    }
    db_D_imUserRelationFree(userRelation2,userRelation2Length);
    db_D_imUserRelationFree(userRelation1,userRelation1Length);
    db_D_imRelationApplicantFree(relationApplicants,relationApplicantLength);

}


/**
 * @brief 查看所有的朋友
 * 
 */
CMD_FUNC(cmd_showAllFriends){
    cJSON * result_json = cJSON_CreateObject();
    cJSON *thirdArray  = cJSON_CreateArray();
    int userRelationLength = 0;
    D_User * userRelation = queryImUserFriendsByUserId(client->user_id,&userRelationLength);
    for(int i=0;i<userRelationLength;++i){
        cJSON * friend = cJSON_CreateObject();
        cJSON_AddNumberToObject(friend,"UserId",*(userRelation[i].id));
        cJSON_AddStringToObject(friend,"UserName", userRelation[i].user_name);
        cJSON_AddStringToObject(friend,"UserNick", userRelation[i].user_nick);
        cJSON_AddItemToObject(thirdArray,"",friend);
    }
    cJSON_AddItemToObject(result_json,"userFriends",thirdArray);
    sendnumeric(client, SHOWALLFRIENDSSUCCESS,cJSON_PrintUnformatted(result_json));
    cJSON_Delete(result_json);
    db_D_UserFree(userRelation,userRelationLength);
}